package com.fox.imagedb.gui;

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

//package components;
/*
 * This code is based on an example provided by Richard Stanford, 
 * a tutorial reader.
 */

import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.text.StyledDocument;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import com.fox.imagedb.listener.PhylTreePopupListener;
import com.fox.imagedb.model.PhylTreeNode;
import com.fox.imagedb.ui.PhylTreeCellRenderer;
import com.fox.imagedb.ui.PhylTreeUI;

public class TreePanel extends JScrollPane implements TreeExpansionListener {

	private static final long serialVersionUID = -7763108936433562689L;

	private PhylTreeNode rootNode;

	private DefaultTreeModel treeModel;

	private JTree tree;

	private Toolkit toolkit = Toolkit.getDefaultToolkit();

	// private PhylTreeXMLParser parser;

	// private PhylTreeXMLWriter xmlWriter;

	public TreePanel(StyledDocument styledDocument) {
		super();
		getVerticalScrollBar().setUnitIncrement(20);

		// FIXME
		// rootNode = new PhylTreeNode("Root Node");
		// parser = new PhylTreeXMLParser();
		// xmlWriter = new PhylTreeXMLWriter();
		tree = new JTree();

		// treeModel = new DefaultTreeModel(new PhylTreeNode());
		// tree.setModel(treeModel);

		populateTree("C:/dev/workspace/PhylTree/phyltree.xml");

		tree.setUI(new PhylTreeUI(styledDocument));
		tree.setCellRenderer(new PhylTreeCellRenderer());
		tree.setEditable(false);
		tree.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);
		tree.setShowsRootHandles(true);

		// On encapsule l'arbre dans un panel pour pas avoir de problemes avec
		// le scrolling
		JPanel panel = new JPanel(new GridLayout(1, 0));
		panel.add(tree);
		setViewportView(panel);

		JPopupMenu popup;

		// ...where the GUI is constructed:
		// Create the popup menu.
		popup = new JPopupMenu();
		JMenuItem menuItem = new JMenuItem("A popup menu item");
		popup.add(menuItem);
		menuItem = new JMenuItem("Another popup menu item");
		popup.add(menuItem);

		// Add listener to components that can bring up popup menus.
		MouseListener popupListener = new PhylTreePopupListener(popup);
		tree.addMouseListener(popupListener);

	}

	public PhylTreeNode addObject(DefaultMutableTreeNode parent, Object child) {
		return addObject(parent, child, false, new ArrayList<String>());
	}

	public PhylTreeNode addObject(DefaultMutableTreeNode parent, Object child,
			boolean shouldBeVisible, List<String> synapomorphies) {

		PhylTreeNode childNode = new PhylTreeNode(child, synapomorphies);
		if (parent == null) {
			parent = rootNode;
		}

		// It is key to invoke this on the TreeModel, and NOT
		// DefaultMutableTreeNode
		treeModel.insertNodeInto(childNode, parent, parent.getChildCount());

		// Make sure the user can see the lovely new node.
		if (shouldBeVisible) {
			tree.scrollPathToVisible(new TreePath(childNode.getPath()));
		}
		return childNode;
	}

	public PhylTreeNode addObject(DefaultMutableTreeNode parent, Object child,
			List<String> synapomorphies) {
		return addObject(parent, child, false, synapomorphies);
	}

	/** Add child to the currently selected node. */
	public PhylTreeNode addObject(Object child, List<String> synapomorphies) {
		PhylTreeNode parentNode = null;
		TreePath parentPath = tree.getSelectionPath();

		if (parentPath == null) {
			parentNode = rootNode;
		} else {
			parentNode = (PhylTreeNode) (parentPath.getLastPathComponent());
		}

		return addObject(parentNode, child, true, synapomorphies);
	}

	/** Remove all nodes except the root node. */
	public void clear() {
		rootNode.removeAllChildren();
		treeModel.reload();
	}

	public PhylTreeNode getRootNode() {
		return rootNode;
	}

	public JTree getTree() {
		return tree;
	}

	public DefaultTreeModel getTreeModel() {
		return treeModel;
	}

	public void populateTree(File file) {
		// treeModel = parser.populateTree(file);
		tree.setModel(treeModel);
		rootNode = (PhylTreeNode) treeModel.getRoot();
	}

	public void populateTree(String filePath) {
		populateTree(new File(filePath));
	}

	/** Remove the currently selected node. */
	public void removeCurrentNode() {
		TreePath currentSelection = tree.getSelectionPath();
		if (currentSelection != null) {
			DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelection
					.getLastPathComponent());
			MutableTreeNode parent = (MutableTreeNode) (currentNode.getParent());
			if (parent != null) {
				treeModel.removeNodeFromParent(currentNode);
				return;
			}
		}

		// Either there was no selection, or the root was selected.
		toolkit.beep();
	}

	public void save(File selectedFile) {
		// xmlWriter.writeXMLFile(selectedFile, rootNode);
	}

	public void setTree(JTree tree) {
		this.tree = tree;
	}

	@Override
	public void treeCollapsed(TreeExpansionEvent event) {
	}

	@Override
	public void treeExpanded(TreeExpansionEvent event) {
	}

}
